/*
 * Copyright (c) 2016. 恒昌互联网运营中心.
 */
package com.credithc.eagleeye.api.service.impl;
import com.credithc.eagleeye.api.factory.ESFactory;
import com.credithc.eagleeye.api.service.SettingService;
import com.credithc.eagleeye.api.service.StatService;
import com.credithc.eagleeye.api.vo.*;
import com.credithc.eagleeye.util.FastJsonConvert;
import com.credithc.eagleeye.util.MixUtil;
import com.credithc.framework.es.util.ElasticSearchUtil;
import com.credithc.framework.utils.date.DateTools;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.Client;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.filters.Filters;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.metrics.avg.Avg;
import org.elasticsearch.search.aggregations.metrics.percentiles.Percentiles;
import org.elasticsearch.search.aggregations.metrics.sum.Sum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
 * 描 述: <br/>
 * 作 者: zhangjin<br/>
 * 创 建：2018年09月27日<br/>
 * 版 本：v1.0.0<br>
 * <p/>
 * 历 史: (版本) 作者 时间 注释 <br/>
 */
@SuppressWarnings("Duplicates")
@Service
@Slf4j
public class StatServiceImpl implements StatService {
    @Autowired
    private SettingService settingService;
    protected List<String> statTerms(String platform, String env,String termFiled) {
        ElasticSearchUtil elasticSearchUtil = ESFactory.getInstance();
        List<String> resultList = new ArrayList<>();
        try {
            Client client = elasticSearchUtil.getEsClient();
            long toTime = System.currentTimeMillis();
            long formTime = toTime-TimeUnit.DAYS.toMillis(1);

            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
            //时间过滤
            boolQueryBuilder.must(QueryBuilders.rangeQuery("requestDateTime").from(formTime).to(toTime));
            //指定平台
            if (StringUtils.isNotBlank(platform)) {
                boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("platformName.raw", platform));
            }
            //指定运行环境
            if (StringUtils.isNotBlank(env)) {
                boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("env", env));
            }

            SearchRequestBuilder searchRequestBuilder = client.prepareSearch("eagle-monitor-*")
                    .setSearchType(SearchType.QUERY_AND_FETCH)
                    .setSize(0)
                    .setTypes("eagle")
                    .setQuery(boolQueryBuilder)
                    .addAggregation(
                            AggregationBuilders.terms("aggsTerm")
                                    .field(termFiled)
                                    .size(20)
                                    .order(Terms.Order.count(false))
                    );
            SearchResponse response = searchRequestBuilder.execute().actionGet();
            Terms aggsTerm = response.getAggregations().get("aggsTerm");

            for(Terms.Bucket resultBk : aggsTerm.getBuckets()) {
                String result = resultBk.getKeyAsString();
                resultList.add(result);
            }

            log.debug(String.format("查询耗时:%sms,聚合数量：%s,详情：%s", response.getTookInMillis(), aggsTerm.getBuckets().size(), FastJsonConvert.convertObjectToJsonWithPrettyFormat(resultList)));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return resultList;
    }

    @Override
    @Cacheable(value="enumCache",key="#platform+#env")
    public EnumVo statEnum(String platform, String env){
        EnumVo enumVo= new EnumVo();
        enumVo.setClientNameList(statTerms(platform,env,"clientName.raw"));
        enumVo.setServiceNameList(statTerms(platform,env,"serviceName.raw"));
        enumVo.setServiceCategoryList(statTerms(platform,env,"serviceCategory.raw"));
        return enumVo;
    }
    private long getFormTime(String fromDate) {
        if(StringUtils.isNotBlank(fromDate)){
            return DateTools.Date19ToDate(fromDate+" 00:00:00").getTime();
        }
        return DateTools.getDateByDateDay(DateTools.Date19ToDate(DateTools.getSysDate10()+" 00:00:00"), -7).getTime();
    }

    private long getToTime(String toDate) {
        String date=toDate;
        if(StringUtils.isBlank(date)){
            date=DateTools.getSysDate10();
        }
        return DateTools.Date19ToDate(date+" 23:59:59").getTime();
    }

    protected BoolQueryBuilder getBoolQueryBuilder(StatConditionVo statConditionVo) {
        long formTime = getFormTime(statConditionVo.getFromDate());
        long toTime = getToTime(statConditionVo.getToDate());

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //时间过滤
        boolQueryBuilder.must(QueryBuilders.rangeQuery("requestDateTime").from(formTime).to(toTime));
        //指定平台
        if (StringUtils.isNotBlank(statConditionVo.getPlatformName())) {
            boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("platformName", statConditionVo.getPlatformName()));
        }
        //指定运行环境
        if (StringUtils.isNotBlank(statConditionVo.getEnv())) {
            boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("env", statConditionVo.getEnv()));
        }
        //指定客户端
        if (StringUtils.isNotBlank(statConditionVo.getClientName())) {
            boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("clientName", statConditionVo.getClientName()));
        }
        //指定模块
        if (StringUtils.isNotBlank(statConditionVo.getServiceCategory())) {
            boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("serviceCategory", statConditionVo.getServiceCategory()));
        }
        //指定服务
        if (StringUtils.isNotBlank(statConditionVo.getServiceName())) {
            boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("serviceName", statConditionVo.getServiceName()));
        }
        return boolQueryBuilder;
    }


    @Override
    public List<StatVo> statError(StatConditionVo statConditionVo) {
        ElasticSearchUtil elasticSearchUtil = ESFactory.getInstance();
        List<StatVo> resultList = new ArrayList<>();
        try {
            Client client = elasticSearchUtil.getEsClient();
            BoolQueryBuilder boolQueryBuilder = getBoolQueryBuilder(statConditionVo);
            SearchRequestBuilder searchRequestBuilder = client.prepareSearch("eagle-monitor-*")
                    .setSearchType(SearchType.QUERY_AND_FETCH)
                    .setSize(0)
                    .setTypes("eagle")
                    .setQuery(boolQueryBuilder)
                    .addAggregation(
                            AggregationBuilders.dateHistogram("aggsDate")
                                    .field("requestDateTime")
                                    .interval(DateHistogramInterval.DAY)
                                    .timeZone("Asia/Shanghai")
                                    .minDocCount(1)
                                    .extendedBounds(getFormTime(statConditionVo.getFromDate()), getToTime(statConditionVo.getToDate()))
                                    .subAggregation(
                                            AggregationBuilders.terms("aggsResult")
                                                    .field("result.raw")
                                                    .size(2)
                                                    .order(Terms.Order.count(false))
                                    )
                    );
            log.debug(searchRequestBuilder.toString());
            SearchResponse response = searchRequestBuilder.execute().actionGet();
            log.debug(response.toString());
            Histogram aggsDate = response.getAggregations().get("aggsDate");
            for(Histogram.Bucket dateBk : aggsDate.getBuckets()) {
                String date = DateTools.FormatDate10(MixUtil.ISO_DATETIME_TIME_ZONE_FORMAT_WITH_MILLIS.parse(dateBk.getKeyAsString()));
                long dateCount = dateBk.getDocCount();
                StatVo dateStatVo = new StatVo();
                dateStatVo.setName(date);
                dateStatVo.setCount(dateCount);
                Terms aggsResult = dateBk.getAggregations().get("aggsResult");
                List<StatVo> subStatVos = new ArrayList<>();
                Map<String, StatVo> subStatMap = new HashMap<>(3);
                for(Terms.Bucket resultBk : aggsResult.getBuckets()) {
                    String result = resultBk.getKeyAsString();
                    long resultCount = resultBk.getDocCount();
                    StatVo resultVo = new StatVo();
                    resultVo.setName(result);
                    resultVo.setCount(resultCount);
                    subStatMap.put(result, resultVo);
                }
                dateStatVo.setSubStatMap(subStatMap);
                resultList.add(dateStatVo);
            }

            log.debug(String.format("查询耗时:%sms,聚合数量：%s,详情：%s", response.getTookInMillis(), aggsDate.getBuckets().size(), FastJsonConvert.convertObjectToJsonWithPrettyFormat(resultList)));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return resultList;
    }

    @Override
    public List<StatVo> statPercent(StatConditionVo statConditionVo) {
        long formTime = getFormTime(statConditionVo.getFromDate());
        long toTime = getToTime(statConditionVo.getToDate());
        DateHistogramInterval interval = DateHistogramInterval.DAY;
        if((toTime - formTime)<TimeUnit.DAYS.toMillis(7)){
            int hours = (int) ((toTime - formTime)  /TimeUnit.HOURS.toMillis(1));
            interval=DateHistogramInterval.hours((hours/12));
        }
        return this.statPercent(statConditionVo,interval);
    }

    @Override
    public List<StatVo> statPercent(StatConditionVo statConditionVo,DateHistogramInterval interval) {

        ElasticSearchUtil elasticSearchUtil = ESFactory.getInstance();
        List<StatVo> resultList = new ArrayList<>();
        try {
            Client client = elasticSearchUtil.getEsClient();
            BoolQueryBuilder boolQueryBuilder = getBoolQueryBuilder(statConditionVo);
            long formTime = getFormTime(statConditionVo.getFromDate());
            long toTime = getToTime(statConditionVo.getToDate());

            SearchRequestBuilder searchRequestBuilder = client.prepareSearch("eagle-monitor-*")
                    .setSearchType(SearchType.QUERY_AND_FETCH)
                    .setSize(0)
                    .setTypes("eagle")
                    .setQuery(boolQueryBuilder)
                    .addAggregation(
                            AggregationBuilders.dateHistogram("aggsDate")
                                    .field("requestDateTime")
                                    .interval(interval)
                                    .timeZone("Asia/Shanghai")
                                    .minDocCount(1)
                                    .extendedBounds(formTime, toTime)
                                    .subAggregation(
                                            AggregationBuilders.percentiles("aggsResult")
                                                    .field("runTime")
                                                    .percentiles(95,99,99.5)
                                    )
                    );
            log.debug(searchRequestBuilder.toString());
            SearchResponse response = searchRequestBuilder.execute().actionGet();
            log.debug(response.toString());
            Histogram aggsDate = response.getAggregations().get("aggsDate");
            for(Histogram.Bucket dateBk : aggsDate.getBuckets()) {
                String date = DateTools.FormatDate19(MixUtil.ISO_DATETIME_TIME_ZONE_FORMAT_WITH_MILLIS.parse(dateBk.getKeyAsString()));
                long dateCount = dateBk.getDocCount();
                StatVo dateStatVo = new StatVo();
                dateStatVo.setName(date);
                dateStatVo.setCount(dateCount);
                Percentiles aggsResult = dateBk.getAggregations().get("aggsResult");
                Map<String, StatVo> subStatMap = new HashMap<>(3);

                double percent95 = aggsResult.percentile(95);
                StatVo resultVo = new StatVo();
                resultVo.setName("95");
                resultVo.setCount(Double.valueOf(percent95).longValue());
                subStatMap.put("95", resultVo);

                double percent99 = aggsResult.percentile(99);
                resultVo = new StatVo();
                resultVo.setName("99");
                resultVo.setCount(Double.valueOf(percent99).longValue());
                subStatMap.put("99", resultVo);

                double percent995 = aggsResult.percentile(99.5);
                resultVo = new StatVo();
                resultVo.setName("99.5");
                resultVo.setCount(Double.valueOf(percent995).longValue());
                subStatMap.put("99.5", resultVo);

                dateStatVo.setSubStatMap(subStatMap);
                resultList.add(dateStatVo);
            }

            log.debug(String.format("查询耗时:%sms,聚合数量：%s,详情：%s", response.getTookInMillis(), aggsDate.getBuckets().size(), FastJsonConvert.convertObjectToJsonWithPrettyFormat(resultList)));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return resultList;
    }

    @Override
    public List<StatVo> statDependency(StatConditionVo statConditionVo) {
        ElasticSearchUtil elasticSearchUtil = ESFactory.getInstance();
        List<StatVo> resultList = new ArrayList<>();
        try {
            Client client = elasticSearchUtil.getEsClient();
            long toTime = System.currentTimeMillis();
            long formTime = toTime- TimeUnit.DAYS.toMillis(1);
            if(StringUtils.isNotBlank(statConditionVo.getFromDate())){
                formTime = DateTools.Date19ToDate(statConditionVo.getFromDate()+" 00:00:00").getTime();
            }
            if(StringUtils.isNotBlank(statConditionVo.getToDate())){
                toTime = DateTools.Date19ToDate(statConditionVo.getToDate()+" 23:59:59").getTime();
            }

            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
            //时间过滤
            boolQueryBuilder.must(QueryBuilders.rangeQuery("requestDateTime").from(formTime).to(toTime));
            //忽略定时任务ice
            boolQueryBuilder.mustNot(QueryBuilders.matchPhraseQuery("serviceName", "taskIceService"));
            //指定平台
            if (StringUtils.isNotBlank(statConditionVo.getPlatformName())) {
                boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("platformName", statConditionVo.getPlatformName()));
            }
            //指定运行环境
            if (StringUtils.isNotBlank(statConditionVo.getEnv())) {
                boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("env", statConditionVo.getEnv()));
            }
            //指定客户端
            if (StringUtils.isNotBlank(statConditionVo.getClientName())) {
                boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("clientName", statConditionVo.getClientName()));
            }
            //指定模块
            if (StringUtils.isNotBlank(statConditionVo.getServiceCategory())) {
                boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("serviceCategory", statConditionVo.getServiceCategory()));
            }
            //指定服务
            if (StringUtils.isNotBlank(statConditionVo.getServiceName())) {
                boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("serviceName", statConditionVo.getServiceName()));
            }
            SearchResponse response = client.prepareSearch("eagle-monitor-*")
                    .setSearchType(SearchType.QUERY_AND_FETCH)
                    .setSize(0)
                    .setTypes("eagle")
                    .setQuery(boolQueryBuilder)
                    .addAggregation(
                            AggregationBuilders.terms("serviceNames").field("serviceCategory.raw").size(20).order(Terms.Order.count(false))
                                    .subAggregation(AggregationBuilders.terms("clientNames").field("clientName.raw").size(20).order(Terms.Order.count(false)))
                    )
                    .execute().actionGet();
            log.debug(response.toString());
            Terms serviceNames = response.getAggregations().get("serviceNames");
            Map<String, StatVo> statVoMap = new HashMap<>();
            for(Terms.Bucket serviceBk : serviceNames.getBuckets()) {
                String serviceName = (String)serviceBk.getKey();
                long serviceCount = serviceBk.getDocCount();
                serviceName=serviceName.replaceAll("IceService","");
                if(serviceName.indexOf("ProductManager")>-1){
                    serviceName="product";
                }else if(serviceName.indexOf("AasAccounting")>-1){
                    serviceName="account";
                }else if(serviceName.indexOf("MarketingAcitvitie")>-1){
                    serviceName="marketing";
                }
                serviceName = serviceName.toLowerCase();
                StatVo seviceStatVo = new StatVo();
                seviceStatVo.setName(serviceName.toLowerCase());
                seviceStatVo.setCount(serviceCount);

                Terms clientNames = serviceBk.getAggregations().get("clientNames");
                List<StatVo> clientStatList = new ArrayList<>();
                for(Terms.Bucket clientBk : clientNames.getBuckets()) {
                    String clientName = ((String)clientBk.getKey()).replaceAll("-ice","");
                    long clientCount = clientBk.getDocCount();
                    StatVo clientStatVo = new StatVo();
                    clientStatVo.setName(clientName);
                    clientStatVo.setCount(clientCount);
                    clientStatList.add(clientStatVo);
                    if (statVoMap.get(clientName) == null) {
                        StatVo tempStatVo = new StatVo();
                        tempStatVo.setName(clientName);
                        tempStatVo.setCount(0);
                        tempStatVo.setSubStatList(new ArrayList<StatVo>());
                        statVoMap.put(clientName, tempStatVo);
                    }
                }
                seviceStatVo.setSubStatList(clientStatList);
                statVoMap.put(serviceName,seviceStatVo);

                log.debug(String.format("serviceCategory:%s,count:%s",serviceName,serviceCount));
            }
            for(Map.Entry<String,StatVo> entry : statVoMap.entrySet()) {
                resultList.add(entry.getValue());
            }

            log.debug(String.format("查询耗时:%sms,聚合数量：%s", response.getTookInMillis(), serviceNames.getBuckets().size()));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return resultList;
    }

    @Override
    public List<StatSunburstVo> statSunburst(StatConditionVo statConditionVo) {
        ElasticSearchUtil elasticSearchUtil = ESFactory.getInstance();
        List<StatSunburstVo> resultList = new ArrayList<>();
        try {
            Client client = elasticSearchUtil.getEsClient();
            long toTime = System.currentTimeMillis();
            long formTime = toTime- TimeUnit.DAYS.toMillis(1);
            if(StringUtils.isNotBlank(statConditionVo.getFromDate())){
                formTime = DateTools.Date19ToDate(statConditionVo.getFromDate()+" 00:00:00").getTime();
            }
            if(StringUtils.isNotBlank(statConditionVo.getToDate())){
                toTime = DateTools.Date19ToDate(statConditionVo.getToDate()+" 23:59:59").getTime();
            }

            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
            //时间过滤
            boolQueryBuilder.must(QueryBuilders.rangeQuery("requestDateTime").from(formTime).to(toTime));
            //忽略定时任务ice
            boolQueryBuilder.mustNot(QueryBuilders.matchPhraseQuery("serviceName", "taskIceService"));
            //指定平台
            if (StringUtils.isNotBlank(statConditionVo.getPlatformName())) {
                boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("platformName", statConditionVo.getPlatformName()));
            }
            //指定运行环境
            if (StringUtils.isNotBlank(statConditionVo.getEnv())) {
                boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("env", statConditionVo.getEnv()));
            }
            //指定客户端
            if (StringUtils.isNotBlank(statConditionVo.getClientName())) {
                boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("clientName", statConditionVo.getClientName()));
            }
            //指定模块
            if (StringUtils.isNotBlank(statConditionVo.getServiceCategory())) {
                boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("serviceCategory", statConditionVo.getServiceCategory()));
            }
            //指定服务
            if (StringUtils.isNotBlank(statConditionVo.getServiceName())) {
                boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("serviceName", statConditionVo.getServiceName()));
            }
            SearchRequestBuilder searchRequestBuilder = client.prepareSearch("eagle-monitor-*")
                    .setSearchType(SearchType.QUERY_AND_FETCH)
                    .setSize(0)
                    .setTypes("eagle")
                    .setQuery(boolQueryBuilder)
                    .addAggregation(
                            AggregationBuilders.terms("platformNames").field("platformName.raw").size(50).order(Terms.Order.count(false))
                                    .subAggregation(AggregationBuilders.terms("clientNames")
                                            .field("clientName.raw")
                                            .size(20)
                                            .order(Terms.Order.count(false))
                                            .subAggregation(AggregationBuilders.filters("results")
                                                    .filter("OK",
                                                            QueryBuilders.boolQuery().must(
                                                                    QueryBuilders.matchPhraseQuery("result.raw", "OK")
                                                            )
                                                    )
                                                    .filter("ERROR",
                                                            QueryBuilders.boolQuery().must(
                                                                    QueryBuilders.matchPhraseQuery("result.raw", "ERROR")
                                                            )
                                                    )
                                            )
                                    )
                    );
            log.debug(searchRequestBuilder.toString());
            SearchResponse response = searchRequestBuilder.execute().actionGet();
            log.debug(response.toString());
            String colorNormal = "#5d8287";
            String colorGreen = "#28B854";
            String colorWaring = "#F8AF43";
            String colorError = "#E8140D";
            String colorErrorSerious = "#7B1652";

            StatSunburstVo statCaifuSunburstVo = new StatSunburstVo("大财富",colorNormal);
            StatSunburstVo statPuhuiSunburstVo = new StatSunburstVo("大普惠",colorNormal);
            StatSunburstVo statJiChuSunburstVo = new StatSunburstVo("基础服务",colorNormal);
            Terms platfromNamesAggs = response.getAggregations().get("platformNames");
            for(Terms.Bucket platformBk : platfromNamesAggs.getBuckets()) {
                String platfromName = (String)platformBk.getKey();
                long platformCount = platformBk.getDocCount();
                PlatformVo platformVo = settingService.loadPlatform(platfromName);
                if(platformVo!=null) {
                    StatSunburstVo platformStatVo = new StatSunburstVo(platformVo.getDescribe(), colorNormal);
                    Terms clientNamesAggs = platformBk.getAggregations().get("clientNames");
                    for(Terms.Bucket clinetBk : clientNamesAggs.getBuckets()) {
                        String clientName = (String) clinetBk.getKey();
                        long clientCount = clinetBk.getDocCount();
                        StatSunburstVo clientStatVo = new StatSunburstVo(clientName, colorNormal);
                        //让每个客户端的大小显示一样
                        clientStatVo.setValue(1);
                        Filters resultsAggs = clinetBk.getAggregations().get("results");
                        long okCount = resultsAggs.getBucketByKey("OK").getDocCount();
                        long errorCount = resultsAggs.getBucketByKey("ERROR").getDocCount();
                        double errorRate = 0;
                        if (okCount > 0) {
                            BigDecimal divide = BigDecimal.valueOf(errorCount).divide(BigDecimal.valueOf(okCount), 6, BigDecimal.ROUND_HALF_UP);
                            errorRate = divide.doubleValue();
                        }
                        clientStatVo.setOkCount(okCount);
                        clientStatVo.setErrorCount(errorCount);
                        //错误率,百分一,千分一,十万分一
                        if (errorRate >= 0.01) {
                            clientStatVo.getItemStyle().setColor(colorErrorSerious);
                        } else if (errorRate > 0.001) {
                            clientStatVo.getItemStyle().setColor(colorError);
                        } else if (errorRate > 0.00001) {
                            clientStatVo.getItemStyle().setColor(colorWaring);
                        } else {
                            clientStatVo.getItemStyle().setColor(colorGreen);
                        }
                        platformStatVo.getChildren().add(clientStatVo);
                        platformStatVo.setOkCount(platformStatVo.getOkCount() + okCount);
                        platformStatVo.setErrorCount(platformStatVo.getErrorCount() + errorCount);
                    }
                    platformStatVo.setValue(platformStatVo.getChildren().size());
                    StatSunburstVo deptStatVo = null;
                    if (platformVo.getDepartment() != null) {
                        if (platformVo.getDepartment().equals("caifu")) {
                            deptStatVo = statCaifuSunburstVo;
                        } else if (platformVo.getDepartment().equals("puhui")) {
                            deptStatVo = statPuhuiSunburstVo;
                        } else if (platformVo.getDepartment().equals("jichu")) {
                            deptStatVo = statJiChuSunburstVo;
                        }
                        if (deptStatVo != null) {
                            deptStatVo.getChildren().add(platformStatVo);
                            deptStatVo.setValue(deptStatVo.getValue() + platformStatVo.getValue());
                            deptStatVo.setOkCount(deptStatVo.getOkCount() + platformStatVo.getOkCount());
                            deptStatVo.setErrorCount(deptStatVo.getErrorCount() + platformStatVo.getErrorCount());
                        }
                    }
                }
            }

            if(statCaifuSunburstVo.getChildren().size()>0) {
                resultList.add(statCaifuSunburstVo);
            }
            if(statPuhuiSunburstVo.getChildren().size()>0) {
                resultList.add(statPuhuiSunburstVo);
            }
            if(statJiChuSunburstVo.getChildren().size()>0) {
                resultList.add(statJiChuSunburstVo);
            }


            log.debug(String.format("查询耗时:%sms,聚合数量：%s", response.getTookInMillis(), platfromNamesAggs.getBuckets().size()));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return resultList;
    }

    @Override
    public List<StatUnionVo> statUnion(StatConditionVo statConditionVo) {
        ElasticSearchUtil elasticSearchUtil = ESFactory.getInstance();
        List<StatUnionVo> resultList = new ArrayList<>();
        try {
            Client client = elasticSearchUtil.getEsClient();

            long formTime = getFormTime(statConditionVo.getFromDate());
            long toTime = getToTime(statConditionVo.getToDate());

            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
            //时间过滤
            boolQueryBuilder.must(QueryBuilders.rangeQuery("statDate").from(formTime).to(toTime));
            //指定平台
            if (StringUtils.isNotBlank(statConditionVo.getPlatformName())) {
                boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("platformName", statConditionVo.getPlatformName()));
            }
            DateHistogramInterval interval = DateHistogramInterval.HOUR;

            if(StringUtils.equals(statConditionVo.getInterval(),"Hour")){
                interval= DateHistogramInterval.HOUR;
            }else if(StringUtils.equals(statConditionVo.getInterval(),"Day")){
                interval= DateHistogramInterval.DAY;
            }else if(StringUtils.equals(statConditionVo.getInterval(),"Week")){
                interval= DateHistogramInterval.WEEK;
            }else if(StringUtils.equals(statConditionVo.getInterval(),"Month")){
                interval= DateHistogramInterval.MONTH;
            }else if(StringUtils.equals(statConditionVo.getInterval(),"Auto")){
                if((toTime-formTime)>TimeUnit.DAYS.toMillis(30)){
                    interval= DateHistogramInterval.MONTH;
                }else if((toTime-formTime)>TimeUnit.DAYS.toMillis(7)){
                    interval= DateHistogramInterval.WEEK;
                }else if((toTime-formTime)>TimeUnit.DAYS.toMillis(2)){
                    interval= DateHistogramInterval.DAY;
                }

            }

            SearchRequestBuilder searchRequestBuilder = client.prepareSearch(".eagleeye-hour-stat")
                    .setSearchType(SearchType.QUERY_AND_FETCH)
                    .setSize(0)
                    .setTypes("stat")
                    .setQuery(boolQueryBuilder)
                    .addAggregation(
                            AggregationBuilders.dateHistogram("aggsDate")
                                    .field("statDate")
                                    .interval(interval)
                                    .timeZone("Asia/Shanghai")
                                    .minDocCount(1)
                                    .extendedBounds(getFormTime(statConditionVo.getFromDate()), getToTime(statConditionVo.getToDate()))
                                    .subAggregation(
                                            AggregationBuilders.terms("aggsPlatforms")
                                            .field("platformName")
                                            .size(100)
                                                .subAggregation(
                                                        AggregationBuilders.sum("sumTotalCount").field("totalCount")
                                                )
                                                .subAggregation(
                                                        AggregationBuilders.sum("sumOkCount").field("okCount")
                                                )
                                                .subAggregation(
                                                        AggregationBuilders.sum("sumErrorCount").field("errorCount")
                                                )
                                                .subAggregation(
                                                        AggregationBuilders.avg("avgPercent99").field("percent99")
                                                )
                                                .subAggregation(
                                                        AggregationBuilders.avg("avgPercent995").field("percent995")
                                                )
                                    )
                    );
            log.info(searchRequestBuilder.toString());
            SearchResponse response = searchRequestBuilder.execute().actionGet();
            log.info(response.toString());

            Histogram aggsDate = response.getAggregations().get("aggsDate");
            for(Histogram.Bucket dateBk : aggsDate.getBuckets()) {
                String date = DateTools.FormatDate19(MixUtil.ISO_DATETIME_TIME_ZONE_FORMAT_WITH_MILLIS.parse(dateBk.getKeyAsString()));
                Terms aggsPlatforms = dateBk.getAggregations().get("aggsPlatforms");

                for(Terms.Bucket platformBk:aggsPlatforms.getBuckets()) {
                    Sum sumTotalCount = platformBk.getAggregations().get("sumTotalCount");
                    Sum sumOkCount = platformBk.getAggregations().get("sumOkCount");
                    Sum sumErrorCount = platformBk.getAggregations().get("sumErrorCount");
                    Avg avgPercent99 = platformBk.getAggregations().get("avgPercent99");
                    Avg avgPercent995 = platformBk.getAggregations().get("avgPercent995");
                    StatUnionVo statUnionVo = new StatUnionVo();
                    statUnionVo.setPlatformName(platformBk.getKeyAsString());
                    statUnionVo.setStatDate(date);
                    statUnionVo.setTotalCount(Double.valueOf(sumTotalCount.getValue()).longValue());
                    statUnionVo.setOkCount(Double.valueOf(sumOkCount.getValue()).longValue());
                    statUnionVo.setErrorCount(Double.valueOf(sumErrorCount.getValue()).longValue());
                    statUnionVo.setPercent99(Double.valueOf(avgPercent99.getValue()).longValue());
                    statUnionVo.setPercent995(Double.valueOf(avgPercent995.getValue()).longValue());
                    resultList.add(statUnionVo);
                }
            }

        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return resultList;
    }
}
